package ru.ifmo.mlarinsky.classificator.providers;

import java.util.*;

import ru.ifmo.mlarinsky.classificator.io.IOUtil;
import ru.ifmo.mlarinsky.classificator.io.InstrumentLoader;
import ru.ifmo.mlarinsky.classificator.model.Instrument;
import ru.ifmo.mlarinsky.classificator.model.InstrumentRegister;
import ru.ifmo.mlarinsky.classificator.model.QuoteDate;
import ru.ifmo.mlarinsky.classificator.model.Vector;

/**
 *
 * @author Михаил
 */
public class DeterminationVectorProvider extends VectorProvider {
    private static final List<Instrument> DEFAULT_INDEXES = 
            InstrumentLoader.loadInstruments(IOUtil.INDEXES_DATA_FILE_PATH, InstrumentLoader.Period.DEFAULT);
    private static final List<Instrument> DEFAULT_INSTRUMENTS = 
            InstrumentLoader.loadInstruments(IOUtil.INSTRUMENTS_DATA_FILE_PATH, InstrumentLoader.Period.DEFAULT);
    private static final QuoteDate DEFAULT_PERIOD_START = QuoteDate.valueOf("01/01/2011");
    private static final int DEFAULT_PERIOD_LENGTH = 6;
    private static final int DEFAULT_STEP = 5;

    private final int step;
    private final String[] dimensions;

    public DeterminationVectorProvider() {
        this(DEFAULT_INSTRUMENTS, DEFAULT_INDEXES, DEFAULT_PERIOD_START, DEFAULT_PERIOD_LENGTH, DEFAULT_STEP);
    }

    public DeterminationVectorProvider(List<Instrument> instruments, List<Instrument> indexes, QuoteDate periodStart,
                                       int periodLength, int step)
    {
        super(instruments, periodStart, periodLength);

        this.step = step;
        this.dimensions = buildDimensions(indexes);
    }

    public List<Vector> getVectors() {
        List<Vector> vectors = new ArrayList<Vector>();

        for (Instrument instrument : instruments) {
            vectors.add(getVector(instrument));
        }

//        for (Instrument index : indexes) {
//            vectors.add(getVector(index));
//        }

        return vectors;
    }

    public String[] getDimensions() {
        return Arrays.copyOf(dimensions, dimensions.length);
    }

    public Vector getVector(Instrument instrument) {
        Double[] values = new Double[dimensions.length];

        for (int i = 0, length = dimensions.length; i < length; i++) {
            Instrument index = InstrumentRegister.getInstrument(dimensions[i]);
            values[i] = instrument.getDetermination(index, periodStart, periodLength, step);
        }

        return new Vector(instrument.getSymbol(), dimensions, values);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        DeterminationVectorProvider provider = (DeterminationVectorProvider) o;

        if (periodLength != provider.periodLength)
            return false;
        if (step != provider.step)
            return false;
        if (instruments != null ? !instruments.equals(provider.instruments) : provider.instruments != null)
            return false;
        if (periodStart != null ? !periodStart.equals(provider.periodStart) : provider.periodStart != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = instruments != null ? instruments.hashCode() : 0;
        result = 31 * result + (periodStart != null ? periodStart.hashCode() : 0);
        result = 31 * result + periodLength;
        result = 31 * result + step;
        return result;
    }

    @Override
    public String toString() {
        return "DeterminationVectorProvider:" +
                "\n\tperiodStart = " + periodStart +
                "\n\tperiodLength = " + periodLength +
                "\n\tstep = " + step;
    }

    private String[] buildDimensions(List<Instrument> indexes) {
        String[] dimensionStrings = new String[indexes.size()];
        int i = 0;
        for (Instrument index : indexes) {
            dimensionStrings[i++] = index.getSymbol();
        }
        return dimensionStrings;
    }
}
